﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Reflection;

namespace Dapper.ExpressionExtension.Resolvers
{
    /// <summary>
    /// 默认解析器
    /// </summary>
    public class DefaultPropertyResolver : IPropertyResolver
    {
        private static readonly HashSet<Type> PrimitiveTypesSet = new HashSet<Type>
        {
            typeof(object),
            typeof(string),
            typeof(Guid),
            typeof(decimal),
            typeof(double),
            typeof(float),
            typeof(DateTime),
            typeof(DateTimeOffset),
            typeof(TimeSpan),
            typeof(byte[]),
        };

        /// <summary>
        /// 解析属性
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public virtual IEnumerable<ColumnPropertyInfo> ResolveProperties(Type type)
        {
            foreach (var property in FilterComplexTypes(type.GetRuntimeProperties()))
            {
                if (!property.IsDefined(typeof(IgnoreAttribute)) && !property.IsDefined(typeof(NotMappedAttribute)))
                {
                    yield return new ColumnPropertyInfo(property);
                }
            }
        }

        /// <summary>
        /// Primitive 类型集
        /// </summary>
        protected virtual HashSet<Type> PrimitiveTypes => PrimitiveTypesSet;

        /// <summary>
        /// 类型过滤
        /// </summary>
        /// <param name="properties"></param>
        /// <returns></returns>
        protected virtual IEnumerable<PropertyInfo> FilterComplexTypes(IEnumerable<PropertyInfo> properties)
        {
            foreach (var property in properties)
            {
                var type = property.PropertyType;
                type = Nullable.GetUnderlyingType(type) ?? type;
                if (type.GetTypeInfo().IsPrimitive || type.GetTypeInfo().IsEnum || PrimitiveTypes.Contains(type))
                {
                    yield return property;
                }
            }
        }
    }
}
